import Zhi from '../bagua/zhi.js'
import Gan from '../bagua/gan.js'
import GuiGod from '../bagua/guiGod.js'
import God12 from '../bagua/god12.js'

import BaseStage from './baseStage.js'

import dictionary from '../bagua/dictionary.js'

/*
  与地支十二宫相关的事物，都归为六壬排布中
*/
class Liuren extends BaseStage {
  constructor(options = {}) {
    super(options)
    
    this.initLiuren()
  }
  
  initLiuren () {
    this.types.push('Liuren')
  }
  
  /* @section static静态方法 */
  /*
    排天盘月将，因为遁甲涉及穿壬，所以写成静态方法
    type = 空串 月将加载时支上，六壬起局用
    type = key 月将加载定局地支上
    type = hour/day/month/year 月将加载时支/日支/月支/年支上，以此类推
    
    eleKey 加入对象后的指定key，默认为yuejiang
  */
  static setYuejiang (stage, type = '', eleKey = 'yuejiang') {
    if (stage.zhiPalaces[0].ele.hasOwnProperty(eleKey)) {
      return
    }
    
    const len = Zhi.zhiList.length
    // 月将加的初始位置
    const zhiStartIndex = type === '' ? 
      stage.date.ganzhi[3].zhi.index :
      Liuren.getZhiStartByTimeKey(stage, type)
    if (zhiStartIndex < 0) { return }
    // 月将的初始索引
    let zhiYuejiangIndex = stage.date.yuejiang.index
    stage.traveZhiByClock(zhiStartIndex, len, (item, index) => {
      item.ele[eleKey] = new Zhi(zhiYuejiangIndex, {
        description: item.description + dictionary.SKY_ZHI,
        yuejiangKey: true
      })
      
      zhiYuejiangIndex = (zhiYuejiangIndex + 1) % len
      return item
    })
  }
  
  /*
    最常规的十二建除排法，六壬、遁甲穿壬
    type = key/hour/day/month/year 因为六壬中十二建并不是起局基础，所以没有空串的默认情况
    其他参数同上
  */
  static setJianchu (stage, type = 'key', eleKey = 'jianchu') {
    if (stage.zhiPalaces[0].ele.hasOwnProperty(eleKey)) {
      return
    }
    
    const len = God12.godList.jianchu.list.length
    const zhiStartIndex = Liuren.getZhiStartByTimeKey(stage, type)
    if (zhiStartIndex < 0) { return }
    
    stage.traveZhiByClock(zhiStartIndex, len, (item, index) => {
      item.ele[eleKey] = new God12(index, 'jianchu', {
        description: item.description + dictionary.JIANCHU,
      })
      
      return item
    })
  }
  
  /*
    排十二宫
    月将加载时支宫上，逆时针行宫，顺排月将，直到卯宫，此时数到的地支就是命宫的位置，阳顺阴逆排12宫
    参数意义同十二建
  */
  static setTwelvePalaces (stage, type = 'key', eleKey = 'twelvePalace') {
    if (stage.zhiPalaces[0].ele.hasOwnProperty(eleKey)) {
      return
    }
    
    // 逆数到卯
    const desPosIndex = 3
    const len = Zhi.zhiList.length
    const zhiStartIndex = Liuren.getZhiStartByTimeKey(stage, type)
    if (zhiStartIndex < 0) { return }
    
    const zhiOffset = (zhiStartIndex - desPosIndex + len) % len
    // 命宫的位置
    const startIndex = (stage.date.yuejiang.index + zhiOffset) % len
    // 注意阳顺阴逆
    const offset = stage.isSolar ? len : (-1) * len
    
    stage.traveZhiByClock(startIndex, offset, (item, index) => {
      item.ele[eleKey] = new God12(index, 'twelvePalace', {
        description: item.description + dictionary.TWELVEPALACE,
      })
      
      return item
    })
  }
  
  /*
    排十二神将
    type = auto day 六壬起局时的默认参数，自动分阴阳贵人，以日干支为用神
    type = 0 1 2 3 遁甲穿壬，一共四个参数，需要详细解析
    type[0] 阴阳贵人 auto自动 solar阳贵人 lunar阴贵人
    type[1] 如何找贵人，确定贵人用神
    type[2] 判断贵人是加在地盘还是天盘，ground排在地盘，sky排在天盘。六壬排盘贵人固定加天盘，此参数为空
    type[3] 在type[2]确定排在天盘的情况下，此参数指定天盘起排的地支位
  */
  static setGuiGods (stage, type = 'auto day', eleKey = 'guiGod') {
    if (stage.zhiPalaces[0].ele.hasOwnProperty(eleKey)) {
      return
    }
    
    const len = Zhi.zhiList.length
    // 空格分离，确认所有设定
    let typeList = type.split(' ')
    
    // type[0] 首先确定阴阳贵人
    if (typeList[0] === 'auto') {
      const timeZhiIndex = stage.date.ganzhi[3].zhi.index
      if (timeZhiIndex >= 3 && timeZhiIndex <= 8) {
        // 卯酉时分定阴阳，卯到申为阳
        typeList[0] = 'solar'
      }
      else {
        typeList[0] = 'lunar'
      }
    }
    const yinyangGuiGod = typeList[0] === 'solar' ? 0 : 1
    
    // type[1] 确定贵人所在地支位，只有年干确定和日干确定两种方法
    let ganzhi = Liuren.getGanzhiByTimeKey(stage, typeList[1])
    if (!ganzhi) {
      return
    }
    // 获取贵人索引
    const guiGodIndexList = stage.timeGod.guiGod(ganzhi, false)
    const zhiPosIndex = guiGodIndexList[yinyangGuiGod]
    
    // type[2] type[3] 共同确定贵人起排点
    // type[2] = ground时，排在地盘
    let zhiStartIndex = zhiPosIndex
    if (typeList[2] !== 'ground') {
      // 六壬排盘默认是以时干起天盘，即月将
      let yuejiangZhiStart = stage.date.ganzhi[3].zhi.index
      if (typeList[2] === 'sky' && typeList[3]) {
        // 穿壬时，要从新确认月将的起排点
        yuejiangZhiStart = Liuren.getZhiStartByTimeKey(stage, typeList[3])
      }
      if (yuejiangZhiStart < 0) { return }
      const yuejiangZhiIndex = stage.date.yuejiang.index
      const yuejiangOffset = zhiPosIndex >= yuejiangZhiIndex ? zhiPosIndex - yuejiangZhiIndex : zhiPosIndex + len - yuejiangZhiIndex
      zhiStartIndex = (yuejiangZhiStart + yuejiangOffset) % len
    }
    
    // 落在亥到辰顺排，落在巳到戌逆排
    const offset = zhiStartIndex >= 5 && zhiStartIndex <= 10 ? (-1) * len : len
    
    stage.traveZhiByClock(zhiStartIndex, offset, (item, index) => {
      item.ele[eleKey] = new GuiGod(index, {
        description: item.description + dictionary.GUIGOD,
      })
      
      return item
    })
  }
  
  /*
    排太阴
    type = key/hour/day/month/year 因为六壬中太阴并不是起局基础，所以没有空串的默认情况
    其他参数同上
  */
  static setTaiyin (stage, type = 'key', eleKey = 'taiyin') {
    if (stage.zhiPalaces[0].ele.hasOwnProperty(eleKey)) {
      return
    }
    
    const len = Zhi.zhiList.length
    const zhiStartIndex = Liuren.getZhiStartByTimeKey(stage, type)
    let zhiTaiyinIndex = stage.timeGod.taiyin.index
    
    stage.traveZhiByClock(zhiStartIndex, len * (-1), (item, index) => {
      item.ele[eleKey] = new Zhi(zhiTaiyinIndex, {
        description: item.description + dictionary.TAIYIN,
      })
      zhiTaiyinIndex = (zhiTaiyinIndex + 1) % len
      return item
    })
  }
  
  /*
    排天干
    type = liuren day 六壬起局时的默认参数，自动分阴阳贵人，以日干支为用神
    type = 0 1 2 遁甲穿壬，一共三个参数，需要详细解析
    type[0] dunjia为穿壬排天干，liuren为六壬排天干
    type[1] 天干的用神参照 key/year/month/day/hour
    type[2] 在type[0]为liuren的情况下，天干要加在天盘上，这里是天盘起排的地支位
  */
  static setLiurenGan (stage, type = 'liuren day', eleKey = 'liurenGan') {
    if (stage.zhiPalaces[0].ele.hasOwnProperty(eleKey)) {
      return
    }
    
    const len = Zhi.zhiList.length
    const ganLen = Gan.ganList.length
    let typeList = type.split(' ')
    
    if (typeList[0] === 'dunjia') {
      // 遁甲式排天干
      // 地支为子，在日干用五鼠遁推出起始天干
      let startGanIndex = stage.date.ganzhi[2].gan.getMouseGanIndex(0)
      stage.traveZhiByClock(0, len, (item, index) => {
        item.ele[eleKey] = new Gan(startGanIndex, {
          description: item.description + dictionary.LIURENGAN,
        })
        startGanIndex = (startGanIndex + 1) % ganLen
        return item
      })
      return
    }
    
    // type[1] 六壬式排天干确认用神
    // 先确认用神
    let ganzhi = Liuren.getGanzhiByTimeKey(stage, typeList[1])
    if (!ganzhi) {
      return
    }
    // 甲对应的地支
    const zhiPosIndex = ganzhi.zhi.prevIndex(ganzhi.gan.index)
    
    // type[2] 确定天干甲起排点
    // 默认为时支
    let yuejiangZhiStart = stage.date.ganzhi[3].zhi.index
    if (typeList[2]) {
      yuejiangZhiStart = Liuren.getZhiStartByTimeKey(stage, typeList[2])
    }
    if (yuejiangZhiStart < 0) { return }
    const yuejiangZhiIndex = stage.date.yuejiang.index
    const yuejiangOffset = zhiPosIndex >= yuejiangZhiIndex ? zhiPosIndex - yuejiangZhiIndex : zhiPosIndex + len - yuejiangZhiIndex
    const zhiStartIndex = (yuejiangZhiStart + yuejiangOffset) % len
    
    stage.traveZhiByClock(zhiStartIndex, len, (item, index) => {
      item.ele[eleKey] = new Gan(index % ganLen, {
        description: item.description + dictionary.LIURENGAN,
      })
      return item
    })
  }
}

export default Liuren